use std::env;
use std::path::{Component, Path, PathBuf};

use crate::CWD ; 

// 
#[inline]
pub fn expand_path(p:impl AsRef<Path>) -> PathBuf {
    _expand_path(p.as_ref()) 
}

#[inline] 
pub fn clean_path(path: impl AsRef<Path>) -> PathBuf{_clean_path(path.as_ref())}

fn _expand_path(p : &Path) -> PathBuf {
    // ${VAR} OR $VAR
    #[cfg(unix)] 
    let re = regex::Regex::new(r"\$(?:\{([^}]+)\}|([a-zA-Z\d_]+))").unwrap() ; 
    
    let s = p.to_string_lossy() ; 
    let s = re.replace(&s , |caps : &regex::Captures| {
        let name = caps.get(2).or_else(|| caps.get(1)).unwrap() ; 
        env::var(name.as_str()).unwrap_or_else(|_| caps.get(0).unwrap().as_str().to_owned())
    }) ;
    
    let p = Path::new(s.as_ref()) ;
    if let Ok(rest) = p.strip_prefix("~") {
        clean_path(dirs::home_dir().unwrap_or_default().join(rest)) 
    }else if p.is_absolute() {
        clean_path(p) 
    }else {
        clean_path(CWD.load().join(p)) 
    }
}


fn _clean_path(path:&Path) -> PathBuf {
    let mut out = vec![] ;
    for c in path.components() {
        match c {
            Component::CurDir => {} 
            Component::ParentDir => match out.last() {
                Some(Component::RootDir) => {} 
                Some(Component::Normal(_)) => _ = out.pop() ,
                None | Some(Component::CurDir) | Some(Component::ParentDir) | Some(Component::Prefix(_)) => out.push(c) , 
            }, 
            c => out.push(c) , 
        }
    }
    if out.is_empty() {
        PathBuf::from(".")  
    }else {
        out.iter().collect() 
    }
}